﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.DTO.Enums;
using Common.DTO.ihopplockDTO;
using DataLayer;
using RSP_Logic;

namespace LogicLayer
{
    public class ResultHandler
    {


        public GameState DetermineGameState(GameEntity game)
        {
            if (!game.ActiveGame && game.Winner == null)
            {
                return GameState.Started;
            }
            if (game.ActiveGame && game.Winner == null)
            {
                return GameState.Playing;
            }
            if (!game.ActiveGame && game.Winner != null)
            {
                return GameState.Finished;
            }
            if (game.ActiveGame && game.Winner != null)
            {
                return GameState.Error;
            }

            throw new Exception("Unreachable code. GameState should have been returned");
        }

        public PlayerEntity DetermineGameWinner(GameEntity game)
        {
            var playerOne = game.PlayerGame.First().Player;
            var playerTwo = game.PlayerGame.Last().Player;

            var playerOneRoundsWon = 0;
            var playerTwoRoundsWon = 0;

            foreach (var gameRound in game.GameRound)
            {
                var winner = DetermineGameRoundWinner(gameRound);
                if (winner == null)
                {
                    continue;
                }

                if (winner.ID == playerOne.ID)
                {
                    playerOneRoundsWon++;
                    continue;
                }
                if (winner.ID == playerTwo.ID)
                {
                    playerTwoRoundsWon++;
                    continue;
                }
            }

            if (playerOneRoundsWon == playerTwoRoundsWon)
            {
                return null;
            }

            // Kolla om spelare kan inta underläge
            var highestValue = Math.Max(playerOneRoundsWon, playerTwoRoundsWon);
            var minimumValue = Math.Min(playerOneRoundsWon, playerTwoRoundsWon);
            var diffBetweenValues = highestValue - minimumValue;
            var roundsLeft = game.NoOfGameRounds - game.GameRound.Count;
            if (diffBetweenValues <= roundsLeft)
            {
                return null;
            }

            return playerOneRoundsWon > playerTwoRoundsWon ? playerOne : playerTwo;
        }

        public PlayerEntity DetermineGameRoundWinner(GameRoundEntity gameRound)
        {
            var playerOne = gameRound.PlayerChoice.First();
            var playerTwo = gameRound.PlayerChoice.Last();

            var winningPlayer = RSPHandler.DetermineWinner((int)playerOne.Choice, (int)playerTwo.Choice);

            switch (winningPlayer)
            {
                default:
                    return null;

                case 0: return playerOne.Player;
                case 1: return playerTwo.Player;
            }
        }

        public PlayerTurn DeterminePlayerTurn(GameEntity game, int playerAskingId)
        {
            GameRoundEntity latestGameRound;
            try
            {
                latestGameRound = game.GameRound.OrderByDescending(x => x.Date).First();
            }
            catch (Exception)
            {
                return PlayerTurn.Unknown;
            }

            if (latestGameRound.PlayerChoice.Count == 2) // FUTURE: Make ambigious for Player Count
            {
                return PlayerTurn.Unknown;
            }

            foreach (var player in latestGameRound.PlayerChoice)
            {
                if (player.PlayerID == playerAskingId)
                {
                    return PlayerTurn.Opponent;
                }
            }

            return PlayerTurn.You;
        }
    }
}
